<template>
    <div class="l-code-mirror">
        <textarea ref="code"></textarea>
    </div>
</template>
<script>
export default {
    name:'l-code-mirror',
    props: {
        value:{},
        mode:{
            type:String,
            default:'application/javascript'
        },
        readOnly:{
            type:Boolean,
            default:false
        },
        isHint:Boolean,
        handleHint:Function
    },
    watch:{
        value:{
            handler(val){
                if(val != this.value2){
                    this.value2 = val
                    this.editor && this.editor.setValue(val)
                    setTimeout(()=>{
                        this.editor && this.editor.refresh()
                    })
                }
            },
            immediate:true
        },
        mode:{
            handler(val){
                this.editor && this.editor.setOption("mode",val)
            },
            immediate:true
        }
    },
    data(){
        return{
            editor:null,
            value2:''
        }
    },
    computed:{
    },
    mounted(){
        this.init()
    },
    beforeDestroy(){
        this.editor.off("change")
        this.editor = null
    },
    methods:{
        init(){
            const options = {
                lineNumbers: true,
                styleActiveLine: true,
                matchBrackets: true,
                readOnly:this.readOnly,
                mode:this.mode,
                //extraKeys:{"Ctrl":'autocomplete'}
            }

            if(this.isHint){
                options.hintOptions = {hint:this.handleShowHint, completeSingle:false}
            }


            this.editor = window.CodeMirror.fromTextArea(this.$refs.code, options)


            this.value2 = this.value
            this.editor.setValue(this.value)

            this.editor.on("change",(instance, change)=>{
                if(this.isHint){
                    if(change.origin !== 'complete' && /^(?!_)(?!.*?_$)[a-zA-Z0-9_\u4e00-\u9fa5]+$/g.test(change.text[0])){
                        instance.showHint()
                    }
                }

                const value = this.editor.getValue()
                this.value2 = value
                this.$emit('input',value)
            })
        },
        handleShowHint(){
            const cur = this.editor.getCursor()
            const token = this.editor.getTokenAt(cur)
            const end = token.end
            const start = token.start
            let list = []
            if(this.handleHint){
                list = this.handleHint(token.string)
            }
            return {list:list,from:window.CodeMirror.Pos(cur.line,start),to:window.CodeMirror.Pos(cur.line,end)}
        }
    }
}
</script>
<style lang="less">
    .l-code-mirror{
        position: relative;
        height: 100%;
        width: 100%;
        box-sizing: border-box;
        .CodeMirror{
            height: 100%;
            width: 100%;
        }
    }
</style>